home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / sound / tiasound.c < prev    next >
C/C++ Source or Header  |  2000-01-29  |  23KB  |  610 lines

  1. /*****************************************************************************/
  2. /*                                                                           */
  3. /* Module:  TIA Chip Sound Simulator                                         */
  4. /* Purpose: To emulate the sound generation hardware of the Atari TIA chip.  */
  5. /* Author:  Ron Fries                                                        */
  6. /*                                                                           */
  7. /* Revision History:                                                         */
  8. /*    10-Sep-96 - V1.0 - Initial Release                                     */
  9. /*    14-Jan-97 - V1.1 - Cleaned up sound output by eliminating counter      */
  10. /*                       reset.                                              */
  11. /*    30-Oct-98 - Modified for use in MESS by Dan Boris                      */
  12. /*                                                                           */
  13. /*                                                                           */
  14. /*                                                                           */
  15. /*****************************************************************************/
  16. /*                                                                           */
  17. /*                 License Information and Copyright Notice                  */
  18. /*                 ========================================                  */
  19. /*                                                                           */
  20. /* TiaSound is Copyright(c) 1996 by Ron Fries                                */
  21. /*                                                                           */
  22. /* This library is free software; you can redistribute it and/or modify it   */
  23. /* under the terms of version 2 of the GNU Library General Public License    */
  24. /* as published by the Free Software Foundation.                             */
  25. /*                                                                           */
  26. /* This library is distributed in the hope that it will be useful, but       */
  27. /* WITHOUT ANY WARRANTY; without even the implied warranty of                */
  28. /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library */
  29. /* General Public License for more details.                                  */
  30. /* To obtain a copy of the GNU Library General Public License, write to the  */
  31. /* Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.   */
  32. /*                                                                           */
  33. /* Any permitted reproduction of these routines, in whole or in part, must   */
  34. /* bear this legend.                                                         */
  35. /*                                                                           */
  36. /*****************************************************************************/
  37.  
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include <time.h>
  41. #include "osd_cpu.h"
  42.  
  43.  
  44.  
  45. /* CONSTANT DEFINITIONS */
  46.  
  47. /* definitions for AUDCx (15, 16) */
  48. #define SET_TO_1     0x00      /* 0000 */
  49. #define POLY4        0x01      /* 0001 */
  50. #define DIV31_POLY4  0x02      /* 0010 */
  51. #define POLY5_POLY4  0x03      /* 0011 */
  52. #define PURE         0x04      /* 0100 */
  53. #define PURE2        0x05      /* 0101 */
  54. #define DIV31_PURE   0x06      /* 0110 */
  55. #define POLY5_2      0x07      /* 0111 */
  56. #define POLY5        0x09      /* 1001 */
  57. #define DIV31_POLY5  0x0a      /* 1010 */
  58. #define POLY5_POLY5  0x0b      /* 1011 */
  59. #define DIV3_PURE    0x0c      /* 1100 */
  60. #define DIV3_PURE2   0x0d      /* 1101 */
  61. #define DIV93_PURE   0x0e      /* 1110 */
  62. #define DIV3_POLY5   0x0OLY9        0x08      /* 1000 */
  63. #define Pf      /* 1111 */
  64.  
  65. #ifndef POLY9
  66. #define POLY9       0x80     /* selects POLY9 or POLY17 */
  67. #endif
  68.  
  69.  
  70. #define DIV3_MASK    0x0c
  71.  
  72. #define AUDC0        0x15
  73. #define AUDC1        0x16
  74. #define AUDF0        0x17
  75. #define AUDF1        0x18
  76. #define AUDV0        0x19
  77. #define AUDV1        0x1a
  78.  
  79. /* the size (in entries) of the 4 polynomial tables */
  80. #define POLY4_SIZE  0x000f
  81. #define POLY5_SIZE  0x001f
  82. #define POLY9_SIZE  0x01ff
  83.  
  84. /* channel definitions */
  85. #define CHAN1       0
  86. #define CHAN2       1
  87.  
  88. #ifndef FALSE
  89. #define FALSE       0
  90. #endif
  91. #ifndef TRUE
  92. #define TRUE        1
  93. #endif
  94.  
  95. /* LOCAL GLOBAL VARIABLE DEFINITIONS */
  96.  
  97. /* structures to hold the 6 tia sound control bytes */
  98. static UINT8 AUDC[2];    /* AUDCx (15, 16) */
  99. static UINT8 AUDF[2];    /* AUDFx (17, 18) */
  100. static UINT8 AUDV[2];    /* AUDVx (19, 1A) */
  101.  
  102. static UINT8 Outvol[2];  /* last output volume for each channel */
  103.  
  104.  
  105. /* Initialze the bit patterns for the polynomials. */
  106.  
  107. /* The 4bit and 5bit patterns are the identical ones used in the tia chip. */
  108. /* Though the patterns could be packed with 8 bits per byte, using only a */
  109. /* single bit per byte keeps the math simple, which is important for */
  110. /* efficient processing. */
  111.  
  112. static UINT8 Bit4[POLY4_SIZE] =
  113.       { 1,1,0,1,1,1,0,0,0,0,1,0,1,0,0 };
  114.  
  115. static UINT8 Bit5[POLY5_SIZE] =
  116.       { 0,0,1,0,1,1,0,0,1,1,1,1,1,0,0,0,1,1,0,1,1,1,0,1,0,1,0,0,0,0,1 };
  117.  
  118. /* I've treated the 'Div by 31' counter as another polynomial because of */
  119. /* the way it operates.  It does not have a 50% duty cycle, but instead */
  120. /* has a 13:18 ratio (of course, 13+18 = 31).  This could also be */
  121. /* implemented by using counters. */
  122.  
  123. static UINT8 Div31[POLY5_SIZE] =
  124.       { 0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0 };
  125.  
  126. /* Rather than have a table with 511 entries, I use a random number */
  127. /* generator. */
  128.  
  129. static UINT8 Bit9[POLY9_SIZE];
  130.  
  131. static UINT8  P4[2]; /* Position pointer for the 4-bit POLY array */
  132. static UINT8  P5[2]; /* Position pointer for the 5-bit POLY array */
  133. static UINT16 P9[2]; /* Position pointer for the 9-bit POLY array */
  134.  
  135. static UINT8 Div_n_cnt[2];  /* Divide by n counter. one for each channel */
  136. static UINT8 Div_n_max[2];  /* Divide by n maximum, one for each channel */
  137.  
  138.  
  139. /* In my routines, I treat the sample output as another divide by N counter. */
  140. /* For better accuracy, the Samp_n_cnt has a fixed binary decimal point */
  141. /* which has 8 binary digits to the right of the decimal point. */
  142.  
  143. static UINT16 Samp_n_max; /* Sample max, multiplied by 256 */
  144. static UINT16 Samp_n_cnt; /* Sample cnt. */
  145.  
  146.  
  147.  
  148. /*****************************************************************************/
  149. /* Module:  Tia_sound_init()                                                 */
  150. /* Purpose: to handle the power-up initialization functions                  */
  151. /*          these functions should only be executed on a cold-restart        */
  152. /*                                                                           */
  153. /* Author:  Ron Fries                                                        */
  154. /* Date:    September 10, 1996                                               */
  155. /*                                                                           */
  156. /* Inputs:  sample_freq - the value for the '30 Khz' Tia audio clock         */
  157. /*          playback_freq - the playback frequency in samples per second     */
  158. /*                                                                           */
  159. /* Outputs: Adjusts local globals - no return value                          */
  160. /*                                                                           */
  161. /*****************************************************************************/
  162.  
  163. void Tia_sound_init (UINT16 sample_freq, UINT16 playback_freq)
  164. {
  165.    UINT8 chan;
  166.    INT16 n;
  167.  
  168.    /* fill the 9bit polynomial with random bits */
  169.    for (n=0; n<POLY9_SIZE; n++)
  170.    {
  171.       Bit9[n] = rand() & 0x01;       /* fill poly9 with random bits */
  172.    }
  173.  
  174.    /* calculate the sample 'divide by N' value based on the playback freq. */
  175.    Samp_n_max = (UINT16)(((UINT32)sample_freq<<8)/playback_freq);
  176.    Samp_n_cnt = 0;  /* initialize all bits of the sample counter */
  177.  
  178.    /* initialize the local globals */
  179.    for (chan = CHAN1; chan <= CHAN2; chan++)
  180.    {
  181.       Outvol[chan] = 0;
  182.       Div_n_cnt[chan] = 0;
  183.       Div_n_max[chan] = 0;
  184.       AUDC[chan] = 0;
  185.       AUDF[chan] = 0;
  186.       AUDV[chan] = 0;
  187.       P4[chan] = 0;
  188.       P5[chan] = 0;
  189.       P9[chan] = 0;
  190.    }
  191. }
  192.  
  193.  
  194. /*****************************************************************************/
  195. /* Module:  tia_w()                                                          */
  196. /* Purpose: To process the latest control values stored in the AUDF, AUDC,   */
  197. /*          and AUDV registers.  It pre-calculates as much information as    */
  198. /*          possible for better performance.  This routine has not been      */
  199. /*          optimized.                                                       */
  200. /*                                                                           */
  201. /* Author:  Ron Fries                                                        */
  202. /* Date:    January 14, 1997                                                 */
  203. /*                                                                           */
  204. /* Inputs:  addr - the address of the parameter to be changed                */
  205. /*          val - the new value to be placed in the specified address        */
  206. /*                                                                           */
  207. /* Outputs: Adjusts local globals - no return value                          */
  208. /*                                                                           */
  209. /*****************************************************************************/
  210.  
  211. void tia_w (UINT16 addr, UINT8 val)
  212. {
  213.     UINT16 new_val = 0;
  214.     UINT8 chan;
  215.  
  216.     /* determine which address was changed */
  217.     switch (addr)
  218.     {
  219.        case AUDC0:
  220.           AUDC[0] = val & 0x0f;
  221.           chan = 0;
  222.           break;
  223.  
  224.        case AUDC1:
  225.           AUDC[1] = val & 0x0f;
  226.           chan = 1;
  227.           break;
  228.  
  229.        case AUDF0:
  230.           AUDF[0] = val & 0x1f;
  231.           chan = 0;
  232.           break;
  233.  
  234.        case AUDF1:
  235.           AUDF[1] = val & 0x1f;
  236.           chan = 1;
  237.           break;
  238.  
  239.        case AUDV0:
  240.           AUDV[0] = (val & 0x0f) << 2;
  241.           chan = 0;
  242.           break;
  243.  
  244.        case AUDV1:
  245.           AUDV[1] = (val & 0x0f) << 2;
  246.           chan = 1;
  247.           break;
  248.  
  249.        default:
  250.           chan = 255;
  251.           break;
  252.     }
  253.  
  254.     /* if the output value changed */
  255.     if (chan != 255)
  256.     {
  257.        /* an AUDC value of 0 is a special case */
  258.        if (AUDC[chan] == SET_TO_1)
  259.        {
  260.           /* indicate the clock is zero so no processing will occur */
  261.           new_val = 0;
  262.  
  263.           /* and set the output to the selected volume */
  264.           Outvol[chan] = AUDV[chan];
  265.        }
  266.        else
  267.        {
  268.           /* otherwise calculate the 'divide by N' value */
  269.           new_val = AUDF[chan] + 1;
  270.  
  271.           /* if bits 2 & 3 are set, then multiply the 'div by n' count by 3 */
  272.           if ((AUDC[chan] & DIV3_MASK) == DIV3_MASK)
  273.           {
  274.              new_val *= 3;
  275.           }
  276.        }
  277.  
  278.        /* only reset those channels that have changed */
  279.        if (new_val != Div_n_max[chan])
  280.        {
  281.           /* reset the divide by n counters */
  282.           Div_n_max[chan] = new_val;
  283.  
  284.           /* if the channel is now volume only or was volume only */
  285.           if ((Div_n_cnt[chan] == 0) || (new_val == 0))
  286.           {
  287.              /* reset the counter (otherwise let it complete the previous) */
  288.              Div_n_cnt[chan] = new_val;
  289.           }
  290.        }
  291.     }
  292. }
  293.  
  294.  
  295. /*****************************************************************************/
  296. /* Module:  Tia_process_2()                                                  */
  297. /* Purpose: To fill the output buffer with the sound output based on the     */
  298. /*          tia chip parameters.  This routine has not been optimized.       */
  299. /*          Though it is not used by the program, I've left it for reference.*/
  300. /*                                                                           */
  301. /* Author:  Ron Fries                                                        */
  302. /* Date:    September 10, 1996                                               */
  303. /*                                                                           */
  304. /* Inputs:  *buffer - pointer to the buffer where the audio output will      */
  305. /*                    be placed                                              */
  306. /*          n - size of the playback buffer                                  */
  307. /*                                                                           */
  308. /* Outputs: the buffer will be filled with n bytes of audio - no return val  */
  309. /*                                                                           */
  310. /*****************************************************************************/
  311.  
  312. void Tia_process_2 (register unsigned char *buffer, register UINT16 n)
  313. {
  314.     register UINT8 chan;
  315.  
  316.     /* loop until the buffer is filled */
  317.     while (n)
  318.     {
  319.        /* loop through the channels */
  320.        for (chan = CHAN1; chan <= CHAN2; chan++)
  321.        {
  322.           /* NOTE: this routine intentionally does not count down to zero */
  323.           /* since 0 is used as a special case - no clock */
  324.  
  325.           /* if the divide by N counter can count down */
  326.           if (Div_n_cnt[chan] > 1)
  327.           {
  328.              /* decrement and loop */
  329.              Div_n_cnt[chan]--;
  330.           }
  331.           /* otherwise if we've reached the bottom */
  332.           else if (Div_n_cnt[chan] == 1)
  333.           {
  334.              /* reset the counter */
  335.              Div_n_cnt[chan] = Div_n_max[chan];
  336.  
  337.              /* the P5 counter has multiple uses, so we inc it here */
  338.              P5[chan]++;
  339.              if (P5[chan] == POLY5_SIZE)
  340.                 P5[chan] = 0;
  341.  
  342.              /* check clock modifier for clock tick */
  343.  
  344.              /* if we're using pure tones OR
  345.                    we're using DIV31 and the DIV31 bit is set OR
  346.                    we're using POLY5 and the POLY5 bit is set */
  347.              if  (((AUDC[chan] & 0x02) == 0) ||
  348.                  (((AUDC[chan] & 0x01) == 0) && Div31[P5[chan]]) ||
  349.                  (((AUDC[chan] & 0x01) == 1) &&  Bit5[P5[chan]]))
  350.              {
  351.                 if (AUDC[chan] & 0x04)       /* pure modified clock selected */
  352.                 {
  353.                    if (Outvol[chan])         /* if the output was set */
  354.                       Outvol[chan] = 0;      /* turn it off */
  355.                    else
  356.                       Outvol[chan] = AUDV[chan];   /* else turn it on */
  357.                 }
  358.                 else if (AUDC[chan] & 0x08)  /* check for p5/p9 */
  359.                 {
  360.                    if (AUDC[chan] == POLY9)  /* check for poly9 */
  361.                    {
  362.                       /* inc the poly9 counter */
  363.                       P9[chan]++;
  364.                       if (P9[chan] == POLY9_SIZE)
  365.                          P9[chan] = 0;
  366.  
  367.                       if (Bit9[P9[chan]])    /* if poly9 bit is set */
  368.                          Outvol[chan] = AUDV[chan];
  369.                       else
  370.                          Outvol[chan] = 0;
  371.                    }
  372.                    else                      /* must be poly5 */
  373.                    {
  374.                       if (Bit5[P5[chan]])
  375.                          Outvol[chan] = AUDV[chan];
  376.                       else
  377.                          Outvol[chan] = 0;
  378.                    }
  379.                 }
  380.                 else  /* poly4 is the only remaining option */
  381.                 {
  382.                    /* inc the poly4 counter */
  383.                    P4[chan]++;
  384.                    if (P4[chan] == POLY4_SIZE)
  385.                       P4[chan] = 0;
  386.  
  387.                    if (Bit4[P4[chan]])
  388.                       Outvol[chan] = AUDV[chan];
  389.                    else
  390.                       Outvol[chan] = 0;
  391.                 }
  392.              }
  393.           }
  394.        }
  395.  
  396.        /* decrement the sample counter - value is 256 since the lower
  397.           byte contains the fractional part */
  398.        Samp_n_cnt -= 256;
  399.  
  400.        /* if the count down has reached zero */
  401.        if (Samp_n_cnt < 256)
  402.        {
  403.           /* adjust the sample counter */
  404.           Samp_n_cnt += Samp_n_max;
  405.  
  406.           /* calculate the latest output value and place in buffer */
  407.           *(buffer++) = Outvol[0] + Outvol[1];
  408.  
  409.           /* and indicate one less byte to process */
  410.           n--;
  411.        }
  412.     }
  413. }
  414.  
  415.  
  416. /*****************************************************************************/
  417. /* Module:  Tia_process()                                                    */
  418. /* Purpose: To fill the output buffer with the sound output based on the     */
  419. /*          tia chip parameters.  This routine has been optimized.           */
  420. /*                                                                           */
  421. /* Author:  Ron Fries                                                        */
  422. /* Date:    September 10, 1996                                               */
  423. /*                                                                           */
  424. /* Inputs:  *buffer - pointer to the buffer where the audio output will      */
  425. /*                    be placed                                              */
  426. /*          n - size of the playback buffer                                  */
  427. /*                                                                           */
  428. /* Outputs: the buffer will be filled with n bytes of audio - no return val  */
  429. /*                                                                           */
  430. /*****************************************************************************/
  431.  
  432. void Tia_process (INT16 *buffer, UINT16 n)
  433. {
  434.     register UINT8 audc0,audv0,audc1,audv1;
  435.     register UINT8 div_n_cnt0,div_n_cnt1;
  436.     register UINT8 p5_0, p5_1,outvol_0,outvol_1;
  437.  
  438.     audc0 = AUDC[0];
  439.     audv0 = AUDV[0];
  440.     audc1 = AUDC[1];
  441.     audv1 = AUDV[1];
  442.  
  443.     /* make temporary local copy */
  444.     p5_0 = P5[0];
  445.     p5_1 = P5[1];
  446.     outvol_0 = Outvol[0];
  447.     outvol_1 = Outvol[1];
  448.     div_n_cnt0 = Div_n_cnt[0];
  449.     div_n_cnt1 = Div_n_cnt[1];
  450.  
  451.     /* loop until the buffer is filled */
  452.     while (n)
  453.     {
  454.        /* Process channel 0 */
  455.        if (div_n_cnt0 > 1)
  456.        {
  457.           div_n_cnt0--;
  458.        }
  459.        else if (div_n_cnt0 == 1)
  460.        {
  461.           div_n_cnt0 = Div_n_max[0];
  462.  
  463.           /* the P5 counter has multiple uses, so we inc it here */
  464.           p5_0++;
  465.           if (p5_0 == POLY5_SIZE)
  466.              p5_0 = 0;
  467.  
  468.           /* check clock modifier for clock tick */
  469.           if  (((audc0 & 0x02) == 0) ||
  470.               (((audc0 & 0x01) == 0) && Div31[p5_0]) ||
  471.               (((audc0 & 0x01) == 1) &&  Bit5[p5_0]))
  472.           {
  473.              if (audc0 & 0x04)       /* pure modified clock selected */
  474.              {
  475.                 if (outvol_0)        /* if the output was set */
  476.                    outvol_0 = 0;     /* turn it off */
  477.                 else
  478.                    outvol_0 = audv0; /* else turn it on */
  479.              }
  480.              else if (audc0 & 0x08)    /* check for p5/p9 */
  481.              {
  482.                 if (audc0 == POLY9)    /* check for poly9 */
  483.                 {
  484.                    /* inc the poly9 counter */
  485.                    P9[0]++;
  486.                    if (P9[0] == POLY9_SIZE)
  487.                       P9[0] = 0;
  488.  
  489.                    if (Bit9[P9[0]])
  490.                       outvol_0 = audv0;
  491.                    else
  492.                       outvol_0 = 0;
  493.                 }
  494.                 else                        /* must be poly5 */
  495.                 {
  496.                    if (Bit5[p5_0])
  497.                       outvol_0 = audv0;
  498.                    else
  499.                       outvol_0 = 0;
  500.                 }
  501.              }
  502.              else  /* poly4 is the only remaining option */
  503.              {
  504.                 /* inc the poly4 counter */
  505.                 P4[0]++;
  506.                 if (P4[0] == POLY4_SIZE)
  507.                    P4[0] = 0;
  508.  
  509.                 if (Bit4[P4[0]])
  510.                    outvol_0 = audv0;
  511.                 else
  512.                    outvol_0 = 0;
  513.              }
  514.           }
  515.        }
  516.  
  517.  
  518.        /* Process channel 1 */
  519.        if (div_n_cnt1 > 1)
  520.        {
  521.           div_n_cnt1--;
  522.        }
  523.        else if (div_n_cnt1 == 1)
  524.        {
  525.           div_n_cnt1 = Div_n_max[1];
  526.  
  527.           /* the P5 counter has multiple uses, so we inc it here */
  528.           p5_1++;
  529.           if (p5_1 == POLY5_SIZE)
  530.              p5_1 = 0;
  531.  
  532.           /* check clock modifier for clock tick */
  533.           if  (((audc1 & 0x02) == 0) ||
  534.               (((audc1 & 0x01) == 0) && Div31[p5_1]) ||
  535.               (((audc1 & 0x01) == 1) &&  Bit5[p5_1]))
  536.           {
  537.              if (audc1 & 0x04)       /* pure modified clock selected */
  538.              {
  539.                 if (outvol_1)        /* if the output was set */
  540.                    outvol_1 = 0;     /* turn it off */
  541.                 else
  542.                    outvol_1 = audv1; /* else turn it on */
  543.              }
  544.              else if (audc1 & 0x08)    /* check for p5/p9 */
  545.              {
  546.                 if (audc1 == POLY9)    /* check for poly9 */
  547.                 {
  548.                    /* inc the poly9 counter */
  549.                    P9[1]++;
  550.                    if (P9[1] == POLY9_SIZE)
  551.                       P9[1] = 0;
  552.  
  553.                    if (Bit9[P9[1]])
  554.                       outvol_1 = audv1;
  555.                    else
  556.                       outvol_1 = 0;
  557.                 }
  558.                 else                        /* must be poly5 */
  559.                 {
  560.                    if (Bit5[p5_1])
  561.                       outvol_1 = audv1;
  562.                    else
  563.                       outvol_1 = 0;
  564.                 }
  565.              }
  566.              else  /* poly4 is the only remaining option */
  567.              {
  568.                 /* inc the poly4 counter */
  569.                 P4[1]++;
  570.                 if (P4[1] == POLY4_SIZE)
  571.                    P4[1] = 0;
  572.  
  573.                 if (Bit4[P4[1]])
  574.                    outvol_1 = audv1;
  575.                 else
  576.                    outvol_1 = 0;
  577.              }
  578.           }
  579.        }
  580.  
  581.        /* decrement the sample counter - value is 256 since the lower
  582.           byte contains the fractional part */
  583.        Samp_n_cnt -= 256;
  584.  
  585.        /* if the count down has reached zero */
  586.        if (Samp_n_cnt < 256)
  587.        {
  588.           /* adjust the sample counter */
  589.           Samp_n_cnt += Samp_n_max;
  590.  
  591.           /* calculate the latest output value and place in buffer */
  592.           *(buffer++) = (outvol_0 + outvol_1) << 8;
  593.  
  594.           /* and indicate one less byte to process */
  595.           n--;
  596.        }
  597.     }
  598.  
  599.     /* save for next round */
  600.     P5[0] = p5_0;
  601.     P5[1] = p5_1;
  602.     Outvol[0] = outvol_0;
  603.     Outvol[1] = outvol_1;
  604.     Div_n_cnt[0] = div_n_cnt0;
  605.     Div_n_cnt[1] = div_n_cnt1;
  606.  
  607. }
  608.  
  609.  
  610.